package com.ruowei.aop.order;

import com.ruowei.common.error.exception.CommonException;
import com.ruowei.modules.foodOrder.web.dto.ReceivingOrderDTO;
import com.ruowei.modules.foodOrder.web.dto.RefundDTO;
import com.ruowei.modules.sys.domain.annotation.OrderLock;
import com.ruowei.modules.sys.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Slf4j
@Component
public class OrderAspect {

    private final RedisUtil redisUtil;

    public OrderAspect(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    @Around("@annotation(orderLock)")
    public Object orderAround(ProceedingJoinPoint joinPoint, OrderLock orderLock) {
        long time = System.currentTimeMillis();

        Object[] args = joinPoint.getArgs();
        String[] paramNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        String orderCode = "";

        for (int i = 0; i < args.length; i++) {
            String paramName = paramNames[i];
            Object arg = args[i];
            if (arg instanceof ReceivingOrderDTO) {
                ReceivingOrderDTO dto = (ReceivingOrderDTO) arg;
                orderCode = dto.getOrderCode();
                if (!redisUtil.lock(orderCode, time)) {
                    throw new CommonException("订单处理中，请稍后再试");
                }
                break;
            }
            if (arg instanceof RefundDTO) {
                RefundDTO dto = (RefundDTO) arg;
                orderCode = dto.getOrderCode();
                if (!redisUtil.lock(orderCode, time)) {
                    throw new CommonException("订单处理中，请稍后再试");
                }
                break;
            }
            if (paramName.equals("orderCode")) {
                orderCode = paramName;
                if (!redisUtil.lock(orderCode, time)) {
                    throw new CommonException("订单处理中，请稍后再试");
                }
                break;
            }
        }
        Object result;
        try {
            result = joinPoint.proceed();
            redisUtil.unlock(orderCode, time);
        } catch (Throwable throwable) {
            redisUtil.unlock(orderCode, time);
            throw new CommonException(((CommonException) throwable).getDetail());
        }
        return result;
    }
}
